Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / cpu / src / N2_Tlb.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: N2_Tlb.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 __N2_Tlb_h__
#define __N2_Tlb_h__
#include "SS_Tlb.h"
#include "N2_TrieTlb.h"
class N2_Tlb : public SS_Tlb
{
public:
enum
{
ITLB_SIZE = 64,
DTLB_SIZE = 128
};
N2_Tlb( Type type, uint_t size );
N2_Tlb( N2_Tlb& tlb );
~N2_Tlb();
// lookup_ra2pa() does a TLB lookup for real addresses. lookup_va2pa() does it
// for virtual addresses. The multi_hit boolean is true when a TTE is returned
// that has overlapping smaller TTEs in the TLB. The multi_hit is false otherwise.
//
// lookup_va2pa() and lookup_ra2pa() don't use mutexes to make them MP safe.
// Doing so will kill the MP performance. Read write lock aren't much better
// either. So we code TLB insert and demap carefully and have lookup allow
// at least one concurrent insert or demap, but no more. This is checked by
// the tlb_access_enter() and tlb_access_leave() routines: e and l will differ
// when lookup overlaps two or more inserts and demaps.
SS_Tte* lookup_ra2pa( SS_Strand* strand, SS_Vaddr ra, uint_t pid, bool* multi_hit )
{
SS_Tte* t;
uint64_t e,l;
do
{
e = tlb_access_enter();
t = trie.lookup(pid,ra,multi_hit);
l = tlb_access_leave();
}
while (e != l);
return t;
}
SS_Tte* lookup_va2pa( SS_Strand* strand, SS_Vaddr va, uint64_t ctxt, uint_t pid, bool* multi_hit )
{
SS_Tte* t;
uint64_t e,l;
do
{
e = tlb_access_enter();
t = trie.lookup(pid,ctxt,va,multi_hit);
l = tlb_access_leave();
}
while (e != l);
return t;
}
// insert_tsb_tte() inserts a TTE into the TLB (autodemapping if neccesary). If the idx is negative
// then the TLB will find a free spot for the TTE. Otherwise the selected index (modulo size()) is used.
// When r is 1 the tte inserted will be marked ra2pa, else it's a va2pa TTE
SS_Tte* insert_tsb_tte( SS_Strand* strand, uint16_t pid, uint64_t tag, uint64_t data, SS_Vaddr va, int idx, int r );
void demap_virt( SS_Strand* strand, uint_t pid, uint_t context, SS_Vaddr va );
void demap_virt( SS_Strand* strand, uint_t pid, uint_t context );
void demap_virt( SS_Strand* strand, uint_t pid );
void demap_real( SS_Strand* strand, uint_t pid, SS_Vaddr va );
void demap_real( SS_Strand* strand, uint_t pid );
void demap_all ( SS_Strand* strand, uint_t pid );
void demap_auto( SS_Strand* strand, SS_Tte* new_tte, uint_t new_idx );
void snapshot( SS_SnapShot& ss, const char* prefix="", const char* inst="inst" );
void insert( SS_Tte* tte );
// set_used() sets the used flag of TLB entry i
void set_used( uint_t i )
{
if (!used[i])
{
used[i] = true;
if (++used_count == tlb_size)
clear_used();
}
}
// clr_used() clears the used flag of TLB entry i
void clr_used( uint_t i )
{
if (used[i])
{
used[i] = false;
--used_count;
}
}
protected:
N2_TrieTlb trie;
static SS_Tlb* n2_clone( SS_Tlb* );
bool* used;
uint_t used_count;
void clear_used()
{
for (uint_t i=0; i < tlb_size; i++)
used[i] = false;
used_count = 0;
}
uint_t get_free_tte()
{
uint_t i;
for (i=0; i < tlb_size; i++)
{
SS_Tte* tte = ptr_table[i];
if (!tte->valid())
return i;
}
for (i=0; i < tlb_size; i++)
if (!used[i])
return i;
clear_used();
return tlb_size - 1;
}
};
#endif