Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_AddressMap.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_AddressMap.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_AddressMap_h__
#define __SS_AddressMap_h__
#include "BL_BitUtility.h"
#include "SS_Types.h"
#include "SS_Access.h"
class SS_AddressMap
{
public:
SS_AddressMap();
~SS_AddressMap();
// Address is the type that describes how objects registered
// with the SS_AddressMap should be addressed. Two modes are
// available: relative or absolute. Relative addressed objects
// can have only one add (one lo to hi range). Absolute objects
// can have multiple add's. Relative addressed objects are in
// general reusable objects, absolute addressed object are far
// more limited in their reuse, however, can be registers at
// multiple address ranges.
enum Addressing
{
REL, // Registered object is base relative addressed
ABS // Registered object is absolute addressed
};
// add() maps a object obj in the address range from lo to hi inclusive.
// The cpu argument is for strand (cpu) access. The extra usr agrument is
// for optinally different behaviour by frontend (usr) access.
// If usr is not given then it defaults to cpu. The rel flags indicated
// whether obj needs to be addressed relative or absolute.
void add( SS_Paddr lo, SS_Paddr hi, void* obj, Addressing rel,
SS_Access::Func cpu, SS_Access::Func usr=0 );
// overwrite the default range_object_not_found routine
void set_fail( void* obj, SS_Access::Func cpu, SS_Access::Func usr=0 )
{
SS_AddressMap::fail->obj = obj;
SS_AddressMap::fail->fun_cpu = cpu;
SS_AddressMap::fail->fun_usr = usr ? usr : cpu;
}
protected:
// The ld(), st(), rd() and wr() access methods expect to get size
// arguments that are a power of two, and the pa to be aligned to
// the size. When addresses, the object sees the relative address:
// e.g. pa - lo (lo is the low address provided to add()).
void cpu( uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )
{
assert(SS_Access::ok(type,pa,size));
find(pa)->cpu(sid,type,pa,size,data);
}
void usr( uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )
{
assert(SS_Access::ok(type,pa,size));
find(pa)->usr(sid,type,pa,size,data);
}
class Range
{
public:
Range()
:
lo(0),
hi(0),
obj(0),
rel(SS_AddressMap::REL),
fun_cpu(0),
fun_usr(0)
{}
Range( SS_Paddr _lo, SS_Paddr _hi, void* _obj, SS_AddressMap::Addressing _rel,
SS_Access::Func _cpu, SS_Access::Func _usr )
:
lo(_lo),
hi(_hi),
rel(_rel),
obj(_obj),
fun_cpu(_cpu),
fun_usr(_usr)
{}
SS_Paddr lo;
SS_Paddr hi;
void* obj;
SS_AddressMap::Addressing rel;
SS_Access::Func fun_cpu;
SS_Access::Func fun_usr;
bool in_range( SS_Paddr pa ) { return (lo <= pa) && (pa <= hi); }
void cpu( uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )
{
(fun_cpu)(obj,sid,type,(rel == SS_AddressMap::REL) ? (pa - lo) : pa,size,data);
}
void usr( uint_t sid, SS_Access::Type type, SS_Paddr pa, uint_t size, uint64_t* data )
{
(fun_usr)(obj,sid,type,(rel == SS_AddressMap::REL) ? (pa - lo) : pa,size,data);
}
};
static void no_access( void*, uint_t, SS_Access::Type, SS_Paddr, uint_t size, uint64_t* data );
Range* find( SS_Paddr pa )
{
if (_size == 0)
return SS_AddressMap::fail;
uint_t l = 0;
uint_t h = _size;
uint_t m = _size >> 1;
Range* r = &table[m];
while (l != m)
{
((pa < r->lo) ? h : l) = m;
m = l + ((h - l) >> 1);
r = &table[m];
}
return r->in_range(pa) ? r : SS_AddressMap::fail;
}
enum { ALLOC = 16 };
static Range* fail; // Default for failing accesses (pa not found)
Range* table; // Sorted table of ranges
uint_t alloc; // Number of allocated ranges
uint_t _size; // Number of added ranges
};
#endif