Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_AsiSpace.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_AsiSpace.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_AsiSpace_h__
#define __SS_AsiSpace_h__
#include "SS_Types.h"
#include "SS_Asi.h"
class SS_Strand;
class SS_Node;
class SS_AsiCtrReg;
class SS_SharedAsiCtrReg;
class SS_AsiSpace
{
public:
SS_AsiSpace();
~SS_AsiSpace();
// merge() this asi space into asi space s (the strand's asi_space (element of asi_map))
void merge( SS_AsiSpace& s );
// set_mask() sets the mask that is applied to address before look up.
void set_mask( SS_Vaddr _mask ) { mask = _mask; }
// get_mask() returns the address mask
SS_Vaddr get_mask() { return mask; }
bool is_empty(SS_Vaddr va) { return size == 0; }
// Error is a return value for rd/wr asi routines to signal
// success or failure. The hardwired values are values exported
// outside our code base, so please don't change these.
enum Error
{
OK = 0, // Accessed asi is ok and value is correct for load
RETRY = 1, // Retry the access, don't advance the pc.
NO_ASI, // Asi number does not exist
NO_READ, // Register at addr can not be read
NO_WRITE, // Register at addr can not be written
NO_VALUE, // As OK but value returned can be overwritten by value sync.
TRAP_PA, // Failed and trap with privileged action trap
TRAP_IA, // Failed and trap with invalid asi trap
TRAP_IPE, // Failed and trap with internal processor error trap
NOT_INIT // Value is uninitailized internally
};
Error ld64( SS_Strand* s, SS_Vaddr addr, uint64_t* data );
Error st64( SS_Strand* s, SS_Vaddr addr, uint64_t data );
Error rd64( SS_Strand* s, SS_Vaddr addr, uint64_t* data );
Error wr64( SS_Strand* s, SS_Vaddr addr, uint64_t data );
typedef Error (*Read) ( SS_Node* obj, void* reg, SS_Strand* s, SS_Vaddr, uint64_t* data );
typedef Error (*Write)( SS_Node* obj, void* reg, SS_Strand* s, SS_Vaddr, uint64_t data );
// ToDo this is a bit too much interface ... remove some, probably the top two
void add( SS_Vaddr va, SS_Node* obj, SS_AsiCtrReg& reg );
void add( SS_Vaddr va, SS_Strand* obj, SS_AsiCtrReg& reg )
{
add(va, (SS_Node*)obj, reg);
}
void add( SS_Vaddr va, SS_Node* obj, SS_SharedAsiCtrReg& reg );
void add( SS_Vaddr va, SS_Strand* obj, SS_SharedAsiCtrReg& reg )
{
add(va, (SS_Node*)obj, reg);
}
void add( SS_Vaddr va, SS_Node* obj, void* reg, Read ld, Write st, Read rd, Write wr );
void add( SS_Vaddr va, SS_Strand* obj, void* reg, Read ld, Write st, Read rd, Write wr )
{
add(va, (SS_Node*)obj, reg, ld, st, rd, wr);
}
void add( SS_Vaddr lo, SS_Vaddr hi, SS_Node* obj, void* reg, Read ld, Write st, Read rd, Write wr );
void add( SS_Vaddr lo, SS_Vaddr hi, SS_Strand* obj, void* reg, Read ld, Write st, Read rd, Write wr )
{
add(lo, hi, (SS_Node*)obj, reg, ld, st, rd, wr);
}
class Range
{
public:
typedef SS_AsiSpace::Read Read;
typedef SS_AsiSpace::Write Write;
Range() : lo(0), hi(0), obj(0), reg(0), ld(0), st(0), rd(0), wr(0) {}
Range( SS_Vaddr _lo, SS_Vaddr _hi, SS_Node* _obj, void* _reg, Read _ld, Write _st, Read _rd, Write _wr )
: lo(_lo), hi(_hi), obj(_obj), reg(_reg), ld(_ld), st(_st), rd(_rd), wr(_wr) {}
SS_Vaddr lo;
SS_Vaddr hi;
SS_Node* obj;
void* reg;
Read ld;
Write st;
Read rd;
Write wr;
bool in_range( SS_Vaddr va ) { return (lo <= va) && (va <= hi); }
};
enum { ALLOC = 256 };
SS_Asi asi; // Set once to this SS_AsiSpace's
// asi number in SS_AsiMap constructor.
// Used for debugging messages.
protected:
static Error no_rd( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t* );
static Error no_wr( SS_Node*, void*, SS_Strand*, SS_Vaddr, uint64_t );
void add( Range* r );
// find() searches for va in the table of ranges.
// If found it returns a pointer to the range that
// maps va. When va is not found it returns a pointer
// to the fail Range.
Range* find( SS_Vaddr va )
{
if (size == 0)
return &fail;
uint_t l = 0;
uint_t h = size;
uint_t m = size >> 1;
Range* r = table[m];
while (l != m)
{
((va < r->lo) ? h : l) = m;
m = l + ((h - l) >> 1);
r = table[m];
}
return r->in_range(va) ? r : &fail;
}
class Block
{
public:
Block( Block* _next=0 ) : next(_next) {}
SS_AsiSpace::Range page[SS_AsiSpace::ALLOC];
Block* next;
};
SS_Vaddr mask;
Range fail; // Default for failing accesses (va not found)
Range** table; // Sorted table of ranges
bool table_copy; // True when the table needs to be copied during merge
Block* block; // List of allocated blocks of ranges
uint_t free_range_index; // Index in block for free Range
uint_t alloc; // Number of allocated ranges
uint_t size; // Number of added ranges
};
#endif